﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Smart.Model.UI
{
    [ObjectSystem]
    public class FrameComponentAwakeSystem : AwakeSystem<FrameComponent,FrameData>
    {
        public override void Awake(FrameComponent self, FrameData frameData)
        {
            self.Awake(frameData);
        }
    }

    [ObjectSystem]
    public class FrameComponentStartSystem : StartSystem<FrameComponent>
    {
        public override void Start(FrameComponent self)
        {
            self.Start();
        }
    }

    public class FrameComponent : Component
    {
        FrameData frameData;
        GameObject frameHandle;
        ResourceComponent resourceComponent;

        public ScriptBinder ScriptBinder
        {
            get;private set;
        }

        public bool Error
        {
            get;private set;
        }

        protected void LogError(string content)
        {
            Error = true;
            Logger.LogError($"<color=#ff0000>{content}</color>");
            this.Dispose();
        }

        public void Awake(FrameData frameData)
        {
            if (null == frameData)
            {
                LogError("[FrameComponent]:界面参数不能为空");
                return;
            }
            this.frameData = frameData;
            this.frameData.frameComponent = this;
            this.frameData.resourceComponent = null;
            this.frameData.frameBundle = null;
            
            resourceComponent = Entry.Instance.ResourceComponent;
            this.frameData.resourceComponent = resourceComponent;
            if (null == resourceComponent)
            {
                LogError("资源管理器不存在");
                return;
            }

            resourceComponent.LoadAssetBundleFromNative(frameData.bundleName, OnLoadFrameBundleSucceed,OnLoadFrameBundleFailed);
            if (Error)
            {
                return;
            }

            Logger.Log($"<color=#00ff00>界面加载成功:[{frameData.bundleName}]:[{frameData.assetName}]</color>");
        }

        protected void OnLoadFrameBundleSucceed(AssetBundle assetBundle)
        {
            if(null == assetBundle)
            {
                LogError("OnLoadFrameBundleSucceed assetBundle Is Null");
                return;
            }
            this.frameData.frameBundle = assetBundle;

            var template = assetBundle.LoadAsset<GameObject>(frameData.assetName);
            if(null == template)
            {
                LogError($"OnLoadFrameBundleSucceed 资源[{frameData.assetName}]不存在与[{frameData.bundleName}]中");
                return;
            }

            var nguiRoot = Entry.Instance.NGUIRootTransform;
            if(null == nguiRoot)
            {
                LogError($"NGUI Root NULL");
                return;
            }

            int childCount = nguiRoot.childCount;
            if (childCount <= 0)
            {
                LogError($"NGUI Root Has No Layers childCount = {childCount}");
                return;
            }

            int realLayer = Mathf.Clamp(frameData.layer, 0, childCount - 1);
            var parent = nguiRoot.GetChild(realLayer);
            if (null == parent)
            {
                LogError($"Can Not Find Layer For UIFrame With Layer = {frameData.layer} RealLayer = {realLayer}");
                return;
            }

            var handle = UnityEngine.Object.Instantiate(template, parent);
            if(null == handle)
            {
                LogError($"界面克隆失败:[AssetBundle:{frameData.bundleName}]:[assetName:{frameData.assetName}]");
                return;
            }

            frameHandle = handle;

            ScriptBinder = frameHandle.GetComponent<ScriptBinder>();
            if (null == ScriptBinder)
            {
                LogError("缺少组件ScriptBinder");
                return;
            }

            //调整层级
            var panels = parent.GetComponentsInChildren<UIPanel>();
            int baseDepth = frameData.layer * 10000;
            for (int i = 0, max = panels.Length; i < max; ++i)
            {
                panels[i].depth = baseDepth + i;
            }

            if (null != frameData.onFrameLoaded)
            {
                try
                {
                    frameData.onFrameLoaded(frameData);
                    frameData.onFrameLoaded = null;
                }
                catch (Exception e)
                {
                    LogError($"界面加载回调onFrameLoaded异常:{e.Message}");
                    return;
                }
            }
        }

        protected void OnLoadFrameBundleFailed()
        {
            LogError($"预制体AssetBundle加载失败:[bundle:{frameData.bundleName}]");
        }

        public void Start()
        {
            if(!Error)
            {
                try
                {
                    if (null != frameData && null != frameData.onFrameVisible)
                        frameData.onFrameVisible();
                }
                catch (Exception e)
                {
                    LogError($"界面显示回调onFrameLoaded异常:{e.Message}");
                    return;
                }
            }
        }

        public override void Dispose()
        {
            if (Disposed)
            {
                return;
            }

            if(null != frameData)
            {
                try
                {
                    if (null != frameData.onFrameDestroy)
                        frameData.onFrameDestroy();
                }
                catch (Exception e)
                {
                    Logger.LogError($"<color=#ff0000>界面显示回调onFrameDestroy异常:{e.Message}</color>");
                }
                frameData.onFrameDestroy = null;
                frameData.onFrameVisible = null;
                frameData = null;
            }

            if(null != frameData)
            {
                if(null != frameData.frameBundle)
                {
                    frameData.frameBundle = null;
                    if(null != resourceComponent)
                        resourceComponent.UnLoadAssetBundle(frameData.bundleName);
                }
                frameData.frameComponent = null;
                frameData.resourceComponent = null;
                Entry.Instance.ObjectPool.PutData(frameData);
                frameData = null;
            }

            ScriptBinder = null;

            if (null != frameHandle)
            {
                UnityEngine.Object.Destroy(frameHandle);
                frameHandle = null;
            }

            base.Dispose();
        }
    }
}